import datetime
import numpy as np
import pandas as pd


class combine_date_value:
	"""
	combine value and date
	mainly to combine value after backtest (either for compound or single)
	the value always start from 1, i.e. the position is the last time point before trading
	however, the date and time is from the first day of trading
	when it's a operation, we use _ to seperate each word, say getdata_RosefinchSQL
	when it's a value, we use Capital Letter to seperate each word
	date is a numpy array with datetime object in it
	value is a numeric value
	"""
	def __init__(self, date, value):
		# to omit the first value 1
		try:
			self.value = value[1:].as_matrix()
		except:
			self.value = value[1:]
			print(
				'value does not need to be convert to numpy array, it is already is! \n')

		try:
			self.date = date[:len(self.value)].as_matrix()
		except:
			self.date = date[:len(self.value)]
			print(
				'dates do not need to be convert to numpy array, it is already is! \n')

	def date_and_value(self, include_first=True, colnames=['date', 'value']):
		if include_first == True:
			PrevDay = self.date[0] - datetime.timedelta(1)
			self.date = np.insert(self.date, 0, PrevDay)
			self.value = np.insert(self.value, 0, 1)
			self.datevalue = pd.DataFrame([self.date, self.value]).transpose()
			self.datevalue.columns = colnames
		else:
			self.datevalue = pd.DataFrame([self.date, self.value]).transpose()
			self.datevalue.columns = colnames


class Returns_calculation:

	# returns is a data frame with first row being date, second row being Returns
	def __init__(self, returns):
		self.returns = returns
		self.returns.columns = ['Date', 'Returns']

	# merge_by_date is to sum over returns of the same date
	def merge_by_date(self):
		MergedReturns = self.returns.groupby(self.returns['Date'])
		MergedReturns = MergedReturns.sum()
		MergedReturns['Date'] = MergedReturns.index
		self.returns = MergedReturns

	def impute_zero_returns(self, tradedates):
		"""
		impute_zero_returns is to compare the trade record with the trading dates
		to find the trading dates with zero returns and fill it in
		tradedates are a pandas series
		"""
		if (type(tradedates) is np.ndarray):
			tradedates = tradedates.reshape(len(tradedates), 1)
			tradedates = pd.DataFrame(tradedates)
			tradedates.columns = ['Date']
		try:
			self.returns = tradedates.merge(self.returns, on='Date', how='left')
			self.returns = self.returns.fillna(0)
		except:
			print('Insert 0 failed \n')

	# add up the returns together to calculate the simple returns
	def returns_to_Simplevalues(self):
		self.SimpleValue = np.cumsum(np.insert(self.returns['Returns'].as_matrix(), 0, 1))